# 引入Student的类
# 引入JsonRespont模块
import hashlib
import json
import os
import uuid

import openpyxl
from django.conf import settings
from django.db.models import Q
from django.http import JsonResponse

from student.models import Student


# Create your views here.


def login_in(request):
    """
    登录
    :param request:
    :return:
    """
    username = request.GET.get('username')
    password = request.GET.get('password')
    account_dict = {'admin': '123456', 'editor': '123456'}
    if account_dict.get(username) is None:
        return JsonResponse({'code': 400, 'data': None, 'message': "此账号不存在"})

    if account_dict.get(username) != password:
        return JsonResponse({'code': 304, 'data': None, 'message': "密码错误"})

    if username == 'admin':
        return JsonResponse({'code': 200, 'data': {'token': 'X-admin'}, 'message': "操作成功"})

    return JsonResponse({'code': 200, 'data': {'token': 'X-editor'}, 'message': "操作成功"})


def student_info(request):
    """
    学生信息
    :param request:
    :return:
    """
    token = request.GET.get('token')
    if token == 'X-admin':
        return JsonResponse(
            {'code': 200, 'data': {'avatar': 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
                                   'name': '黄晓果', 'roles': ['admin']}})
    return JsonResponse(
        {'code': 200, 'data': {'avatar': 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
                               'name': '黄晓果', 'roles': ['editor']}})


def take_out(request):
    """
    退出登录
    :param request:
    :return:
    """
    return JsonResponse({'code': 200, 'data': 'success', 'message': "操作成功"})


def get_students(request):
    """
    获取所有学生的信息
    :param request:
    :return:
    """
    try:
        perpage = int(request.GET.get('perpage'))
        page = int(request.GET.get('page'))
        # 使用ORM获取所有学生信息
        obj_students = Student.objects.all()[page * perpage - perpage:page * perpage].values()
        # 把结果转为list
        students = list(obj_students)

        total = Student.objects.count()
        # 返回
        return JsonResponse({'code': 200, 'data': {'total': total, 'lists': students}, "message": "操作成功"})
    except Exception as e:
        # 如果出现异常，返回
        return JsonResponse({'code': 500, 'message': "获取学生信息出现异常：%s" % (str(e))})


def query_students(request):
    """
    查询学生信息
    :param request:
    :return:
    """
    # 接收传递过来的查询添加 —————— axios 默认是json --字典类型（‘inputstr’） ---data['inputstr']
    data = json.loads(request.body.decode('utf-8'))
    perpage = int(data['perpage'])
    page = int(data['page'])
    try:
        # 使用ORM获取满足条件的学生信息 并把对象转为字典格式
        obj_students = Student.objects.filter(Q(sno__icontains=data['inputstr']) |
                                              Q(name__icontains=data['inputstr']) |
                                              Q(gender__icontains=data['inputstr']) |
                                              Q(mobile__icontains=data['inputstr']) |
                                              Q(email__icontains=data['inputstr']) |
                                              Q(address__icontains=data['inputstr'])).values()
        total = obj_students.count()
        # 把结果转为list
        students = list(obj_students[page * perpage - perpage:page * perpage])
        # 返回
        return JsonResponse({'code': 200, 'data': {'total': total, 'lists': students}, "message": "操作成功"})
    except Exception as e:
        # 如果出现异常，返回
        return JsonResponse({'code': 500, 'message': "查询学生信息出现异常：%s" % (str(e))})


def is_exsits_sno(request):
    """
    判断学号是否存在
    :param request:
    :return:
    """
    # 接收传递过来的学号
    data = json.loads(request.body.decode('utf-8'))
    try:
        obj_students = Student.objects.filter(sno=data['sno']).values()
        if obj_students.count() == 0:
            return JsonResponse({'code': 200, 'data': 0, "message": "当前学号不存在"})
        else:
            return JsonResponse({'code': 200, 'data': 1, "message": "当前学号已存在"})
    except Exception as e:
        return JsonResponse({'code': 500, 'message': "校验学号失败：%s" % (str(e))})


def add_student(request):
    """
    添加学生到数据库
    :param request:
    :return:
    """
    # 接收传递过来的学号
    data = json.loads(request.body.decode('utf-8'))
    try:
        # 添加到数据库
        obj_students = Student(sno=data['sno'], name=data['name'],
                               gender=data['gender'], birthday=data['birthday'],
                               mobile=data['mobile'], email=data['email'],
                               address=data['address'], image=data['image'])
        # 执行添加
        obj_students.save()
        # 返回
        return JsonResponse({'code': 200, 'data': "添加学员成功", "message": "操作成功"})
    except Exception as e:
        return JsonResponse({'code': 500, 'message': "添加学生异常：%s" % (str(e))})


def update_student(request):
    """
    修改学生到数据库
    :param request:
    :return:
    """
    # 接收传递过来的学号
    data = json.loads(request.body.decode('utf-8'))
    try:
        # 查找到修改学生的信息
        obj_student = Student.objects.get(sno=data['sno'])

        obj_student.name = data['name']
        obj_student.gender = data['gender']
        obj_student.birthday = data['birthday']
        obj_student.mobile = data['mobile']
        obj_student.email = data['email']
        obj_student.address = data['address']
        obj_student.image = data['image']

        obj_student.save()
        # 返回
        return JsonResponse({'code': 200, 'data': "修改学员成功", "message": "操作成功"})
    except Exception as e:
        return JsonResponse({'code': 500, 'message': "修改学生异常：%s" % (str(e))})


def delete_student(request):
    """
    删除学生信息
    :param request:
    :return:
    """
    # 接收传递过来的学号
    data = json.loads(request.body.decode('utf-8'))
    try:
        # 查找到修改学生的信息
        obj_student = Student.objects.get(sno=data['sno'])

        obj_student.delete()
        # 返回
        return JsonResponse({'code': 200, 'data': "删除学员成功", "message": "操作成功"})
    except Exception as e:
        return JsonResponse({'code': 500, 'message': "删除学生异常：%s" % (str(e))})


def delete_students(request):
    """
    批量删除学生信息
    :param request:
    :return:
    """
    # 接收传递过来的学号
    data = json.loads(request.body.decode('utf-8'))
    try:
        # 遍历传递的集合
        for one_student in data['students']:
            # 查询当前记录
            obj_student = Student.objects.get(sno=one_student['sno'])
            # 执行删除
            obj_student.delete()
        # 返回
        return JsonResponse({'code': 200, 'data': "删除学员成功", "message": "操作成功"})
    except Exception as e:
        return JsonResponse({'code': 500, 'message': "删除学生异常：%s" % (str(e))})


def upload(request):
    """
    接收上传的文件
    :param request:
    :return:
    """
    # 接收上传的文件
    rev_file = request.FILES.get('avatar')
    # 判断，是否有文件
    if not rev_file:
        return JsonResponse({'code': 500, "message": "上传文件不能为空"})
    # 获得一个唯一名字：uuid +hash
    new_name = get_random_str()
    # 准备写入URL
    file_path = os.path.join(settings.MEDIA_ROOT, new_name + os.path.splitext(rev_file.name)[1])
    # 开始写入本地磁盘
    try:
        f = open(file_path, 'wb')
        # 多次写入
        for i in rev_file.chunks():
            f.write(i)

        # 写完之后要关闭
        f.close()
        # 返回
        return JsonResponse({'code': 200, "data": "/media/" + new_name + os.path.splitext(rev_file.name)[1],
                             "message": "文件上传成功"})
    except Exception as e:
        return JsonResponse({'code': 500, "message": "文件上传失败：" + str(e)})


def get_random_str():
    """获取UUID"""
    uuid_val = uuid.uuid4()
    uuid_str = str(uuid_val).encode('utf-8')
    md5 = hashlib.md5()
    md5.update(uuid_str)
    return md5.hexdigest()


def import_student_excel(request):
    """
    从excel批量导入学生信息
    :param request:
    :return:
    """
    # ===================== 1.接收Excel文件存储到media文件夹 =======================
    rev_file = request.FILES.get('excel')
    # 判断，是否有文件
    if not rev_file:
        return JsonResponse({'code': 500, "message": "上传文件不能为空"})
    # 获得一个唯一名字：uuid +hash
    new_name = get_random_str()
    # 准备写入URL
    file_path = os.path.join(settings.MEDIA_ROOT, new_name + os.path.splitext(rev_file.name)[1])
    # 开始写入本地磁盘
    try:
        f = open(file_path, 'wb')
        # 多次写入
        for i in rev_file.chunks():
            f.write(i)

        # 写完之后要关闭
        f.close()
    except Exception as e:
        return JsonResponse({'code': 500, "message": "文件上传失败：" + str(e)})

    # ===================== 2.读取存储在Media文件夹的数据 =====================
    ex_students = read_excel_dict(file_path)
    # ===================== 3.把读取的数据存储到数据库 =====================
    success = 0
    error = 0
    error_snos = []
    print(len(ex_students))
    print(ex_students)
    for one_student in ex_students:
        try:
            # obj_student = Student(sno=one_student['sno'], name=one_student['name'],
            #                       gender=one_student['gender'], birthday=one_student['birthday'],
            #                       mobile=one_student['mobile'], email=one_student['email'],
            #                       address=one_student['address'])
            obj_student = Student.objects.create(sno=one_student['sno'], name=one_student['name'],
                                                 gender=one_student['gender'], birthday=one_student['birthday'],
                                                 mobile=one_student['mobile'], email=one_student['email'],
                                                 address=one_student['address'])
            obj_student.save()
            # 计数
            success += 1
        except Exception as e:
            error += 1
            error_snos.append(one_student['sno'])
    # ===================== 4.返回——导入信息 =====================
    return JsonResponse(
        {'code': 200, "data": {"success": success, "error": error, "info": error_snos}, "message": "操作成功"})


def read_excel_dict(path: str):
    """
    读取excel数据
    :param path:
    :return:
    """
    # 实例化一个wrokbook
    wrokbook = openpyxl.load_workbook(path)
    # 实例化一个sheet('student':指的是默认读取student表格)
    sheet = wrokbook['student']
    # 定义一个变量存储最终的数据
    students = []
    # 准备key
    keys = ['sno', 'name', 'gender', 'birthday', 'mobile', 'email', 'address']
    # 遍历
    for row in sheet.rows:
        # 定义一个临时的字典
        temp_dict = {}
        # 组合值和key
        for index, cell in enumerate(row):
            # 组合
            if keys[index] == 'sno' and cell.value is None:
                break
            temp_dict[keys[index]] = cell.value
        # 附加到list中
        if temp_dict:
            students.append(temp_dict)
    # 返回
    if len(students) > 0:
        return students[1:]
    else:
        return students


def export_student_excel(request):
    """
    导出数据到excel
    :param request:
    :return:
    """
    obj_student = Student.objects.all().values()
    students = list(obj_student)
    excel_name = get_random_str() + '.xlsx'
    # 准备写入的路径
    path = os.path.join(settings.MEDIA_ROOT, excel_name)
    # 写入到Excel
    write_to_excel(students, path)
    # 返回
    return JsonResponse(
        {'code': 200, "data": "/media/" + excel_name, "message": "操作成功"})


def write_to_excel(data: list, path: str):
    """
    把数据库写入excel
    :param data:
    :param path:
    :return:
    """
    # 实例化一个wrokbook
    wrokbook = openpyxl.Workbook()
    # 激活一个sheet
    sheet = wrokbook.active
    # 为sheet命名
    sheet.title = 'student'
    # 准备keys
    keys = data[0].keys()
    # 写标题的第一行
    for index, item in enumerate(Student.get_title_list()):
        sheet.cell(row=1, column=index + 1, value=item)
    # 准备写入数据
    for index, item in enumerate(data):
        # 遍历每个元素
        for k, v in enumerate(keys):
            # 这里要从第二列开始
            sheet.cell(row=index + 2, column=k + 1, value=str(item[v]))
    # 写入到文件
    wrokbook.save(path)
